package com.bdd.jpa.service.message.impl;

import com.bdd.jpa.common.MessageStatus;
import com.bdd.jpa.common.MessageType;
import com.bdd.jpa.entity.domain.Message;
import com.bdd.jpa.entity.domain.ScheduleJob;
import com.bdd.jpa.entity.dto.MessageDto;
import com.bdd.jpa.entity.vo.MessageVo;
import com.bdd.jpa.repository.message.MessageRepository;
import com.bdd.jpa.service.message.MessageService;
import com.bdd.jpa.service.schedule.JobService;
import com.bdd.jpa.util.CronUtil;
import com.bdd.jpa.util.ParamsUtil;
import com.bdd.jpa.util.entity.ParamsObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author Bdd
 * @Description
 * @Date 2019/9/23 16:28
 */
@Service
public class MessageServiceImpl implements MessageService {

    private final static String JOB_NAME_SEPARATE = "_";

    @Autowired
    private MessageRepository messageRepository;

    @Autowired
    private JobService jobService;

    /**
     * 只有定时发送，需根据具体业务进行修改
     *
     * @param messageDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean save(MessageDto messageDto) throws Exception {
        Message message = new Message();
        BeanUtils.copyProperties(messageDto, message);
        message.setStatus(MessageStatus.NOT_SEND.getState());
        Message result = messageRepository.save(message);
        jobService.addJob(createScheduleJob(result));
        return true;
    }

    @Override
    public Boolean update(MessageDto messageDto) throws Exception {
        Message message = new Message();
        BeanUtils.copyProperties(messageDto, message);
        message.setStatus(MessageStatus.NOT_SEND.name());
        Message result = messageRepository.save(message);
        jobService.modifyJob(createScheduleJob(result));
        return true;
    }

    @Override
    public Boolean delete(Long id) throws SchedulerException, JsonProcessingException {
        Message result = messageRepository.findByIdAndStatus(id, MessageStatus.NOT_SEND.getState());
        if (result != null && result.getId() != null) {
            messageRepository.deleteById(id);
            jobService.deleteJob(createScheduleJob(result));
            return true;
        }
        return false;
    }

    @Override
    public MessageVo details(Long id) {
        Message result = messageRepository.findById(id).get();
        MessageVo messageVo = new MessageVo();
        BeanUtils.copyProperties(result, messageVo);
        return messageVo;
    }

    @Override
    public List<MessageVo> list() {
        List<Message> result = (List<Message>) messageRepository.findAll();
        List<MessageVo> list = new ArrayList<>();
        result.forEach(item -> {
            MessageVo temp = new MessageVo();
            BeanUtils.copyProperties(item, temp);
            list.add(temp);
        });
        return list;
    }

    /**
     * 创建ScheduleJob对象
     *
     * @param message
     * @return
     */
    private ScheduleJob createScheduleJob(Message message) throws JsonProcessingException {
        ScheduleJob scheduleJob = new ScheduleJob();

        //基本信息
        scheduleJob.setJobName(message.getId() + JOB_NAME_SEPARATE + message.getName());
        scheduleJob.setJobType(message.getType());
        scheduleJob.setJobStatus(message.getStatus());

        //消息类型及调用类与方法
        MessageType messageType = MessageType.valueOf(message.getType());
        createClass(messageType, scheduleJob,"name");

        //设置cron
        scheduleJob.setCronExpression(CronUtil.getCron(message.getDate()));
        scheduleJob.setJobStatus(message.getStatus());

        return scheduleJob;
    }

    /**
     * 创建scheduleJob参数
     *
     * @param messageType
     * @param scheduleJob
     * @param params
     */
    public void createClass(MessageType messageType, ScheduleJob scheduleJob, Object... params) throws JsonProcessingException {
        scheduleJob.setClassName(messageType.getClassName());
        scheduleJob.setMethodName(messageType.getMethodName());
        scheduleJob.setParams(createParams(params));
    }


    /**
     * 创建参数
     *
     * @param objects
     * @return
     */
    private String createParams(Object... objects) throws JsonProcessingException {
        return ParamsUtil.paramsListToJSON(
                Arrays.stream(objects).parallel().
                        map(item -> new ParamsObject(item.getClass().getName(), item))
                .collect(Collectors.toList()));
    }

}